using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System;
using System.Xml;
using CSP.Core;
using Microsoft.Win32;

namespace CSP.MembershipInterface.ConfigFileUpdater
{
	/// <summary>
	/// SQL DataBase installer
	/// </summary>
	[RunInstaller(true)]
	public class ScriptInstall : Installer
	{
		private Container components=null;
		
		public ScriptInstall()
		{
			// This call is required by the Designer.
			InitializeComponent();
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{

		}
		#endregion


        private void InstallIIS6(string targetSite, string folder, string connStringRegKey, string endpointRegKey)
        {

            try
            {
                string path = Environment.GetFolderPath(Environment.SpecialFolder.System);
                path = System.IO.Path.Combine(path, Constants.IIS6ConfigFileName);

                System.Xml.XPath.XPathDocument document = new System.Xml.XPath.XPathDocument(path);
                System.Xml.XPath.XPathNavigator navigator = document.CreateNavigator();
                navigator.MoveToChild(System.Xml.XPath.XPathNodeType.Element);

                System.Xml.XmlNamespaceManager resolver = new System.Xml.XmlNamespaceManager(navigator.NameTable);
                string defaultNamespace = navigator.LookupNamespace(String.Empty);

                resolver.AddNamespace("iis", defaultNamespace);
                string xfolder = folder == string.Empty ? "" : "/" + folder;

                System.Xml.XPath.XPathNodeIterator iter = navigator.Select(string.Format("//iis:IIsWebVirtualDir[@Location='{0}/Root{1}']", targetSite, xfolder), resolver);

                if (iter.Count == 0)
                {
                    iter = navigator.Select(string.Format("//iis:IIsWebVirtualDir[@Location='{0}/root{1}']", targetSite, xfolder), resolver);
                }
                if (iter.Count == 0)
                {
                    throw new ApplicationException("IIS Configuration error");
                }

                while (iter.MoveNext())
                {
                    System.Xml.XPath.XPathNavigator node = iter.Current;
                    string destination = node.GetAttribute("Path", string.Empty);
                    string webConfigFilePath = Path.Combine(destination, "web.config.template");
                    XmlDocument xdoc = new XmlDocument();
                    xdoc.Load(webConfigFilePath);
                    // If the package contains a connection string to be auto-filled
                    if (connStringRegKey != string.Empty)
                    {
                        XmlNode connectionStringNode = xdoc.SelectSingleNode("//configuration/appSettings/add[@key='ConnectionString']");
                        string connectionString = CSP.Core.RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, connStringRegKey);

                        connectionStringNode.Attributes["value"].Value = connectionString;
                    }
                    System.Xml.XPath.XPathNodeIterator iter2 = navigator.Select(string.Format("//iis:IIsWebServer[@Location='{0}']", targetSite), resolver);
                    if (iter2.Count > 0)
                    {
                        iter2.MoveNext();
                        node = iter2.Current;
                        string url = node.GetAttribute("ServerBindings", String.Empty);
                        string[] segments = url.Split(":".ToCharArray());
                        url = "http://" + (segments[2] == string.Empty ? "localhost" : segments[2]) + (segments[1] == "80" ? "" : ":" + segments[1]) + "/" + folder;
                        XmlNode WCFNode = xdoc.SelectSingleNode("//configuration/system.serviceModel/services/service/host/baseAddresses/add");
                        WCFNode.Attributes["baseAddress"].Value = url;

                        CSP.Core.RegistryAccess.CreateStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, endpointRegKey, url + "MembershipServiceClass.svc");
                    }
                    xdoc.Save(Path.Combine(destination,"web.config"));
                    System.IO.File.Delete(webConfigFilePath);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        
        private void InstallIIS7(string targetSite, string folder, string connStringRegKey, string endpointRegKey)
        {

            try
            {
                // First we locate the IIS config file
                string path = Environment.GetFolderPath(Environment.SpecialFolder.System);
                path = System.IO.Path.Combine(path, Constants.IIS7ConfigFileName);

                XmlDocument IISConfigXmlDocument = new XmlDocument();
                IISConfigXmlDocument.Load(path);


                // We get the IIS Site node within the file and all the information we need
                string siteId = targetSite.Substring(targetSite.LastIndexOf("/") + 1);

                XmlNode IISSiteNode = IISConfigXmlDocument.SelectSingleNode(string.Format("//configuration/system.applicationHost/sites/site[@id='{0}']", siteId));

                string physicalPath = IISSiteNode.SelectSingleNode("application/virtualDirectory").Attributes["physicalPath"].Value;
                string protocol = IISSiteNode.SelectSingleNode("bindings/binding").Attributes["protocol"].Value;
                string bindings = IISSiteNode.SelectSingleNode("bindings/binding").Attributes["bindingInformation"].Value;
                string[] segments = bindings.Split(":".ToCharArray());
                string url = protocol + "://" + (segments[2] == string.Empty ? "localhost" : segments[2]) + (segments[1] == "80" ? "" : ":" + segments[1]) + "/" + folder;

                // We locate the web.config.template within the installation folder
                string installationFolder = Path.Combine(physicalPath, folder);

                XmlDocument webConfigTemplateDocument = new XmlDocument();
                string webConfigFilePath = Path.Combine(installationFolder, "web.config.template");
                webConfigTemplateDocument.Load(webConfigFilePath);

                if (connStringRegKey != string.Empty)
                {
                    // We change the connection string node
                    XmlNode connectionStringNode = webConfigTemplateDocument.SelectSingleNode("//configuration/appSettings/add[@key='ConnectionString']");
                    string connectionString = CSP.Core.RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, connStringRegKey);
                    connectionStringNode.Attributes["value"].Value = connectionString;
                }

                // We change the endpoint node
                XmlNode WCFNode = webConfigTemplateDocument.SelectSingleNode("//configuration/system.serviceModel/services/service/host/baseAddresses/add");
                WCFNode.Attributes["baseAddress"].Value = url;

                CSP.Core.RegistryAccess.CreateStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, endpointRegKey, url + "/MembershipServiceClass.svc");

                
                webConfigTemplateDocument.Save(Path.Combine(installationFolder, "web.config"));
                File.Delete(webConfigFilePath);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

		public override void Install(IDictionary stateSaver)
		{
			base.Install (stateSaver);

            string targetSite = this.Context.Parameters["ts"];
            string folder = this.Context.Parameters["tv"];
            string endpointRegKey = this.Context.Parameters["epreg"];

            string connStringRegKey = this.Context.Parameters["csreg"]==null?string.Empty:this.Context.Parameters["csreg"];

            string path = Environment.GetFolderPath(Environment.SpecialFolder.System);
            path = System.IO.Path.Combine(path, Constants.IIS7ConfigFileName);

            if (System.IO.File.Exists(path))
            {
                InstallIIS7(targetSite, folder, connStringRegKey, endpointRegKey);
            }
            else
            {
                InstallIIS6(targetSite, folder, connStringRegKey, endpointRegKey);
            }

        }

        public override void Commit(IDictionary savedState)
        {
            base.Commit(savedState);
        }

        public override void Rollback(IDictionary savedState)
        {
            base.Rollback(savedState);
        }

		public override void Uninstall(IDictionary savedState)
		{
			base.Uninstall (savedState);
		}

 

	}
}
